/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.pdx.cs.guavadata.query;

import edu.pdx.cs.guavadata.Channel;
import edu.pdx.cs.guavadata.Transform;
import edu.pdx.cs.guavadata.domain.Domain;
import edu.pdx.cs.guavadata.domain.Enumerated;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 *
 * @author VuTran
 */
public class PivotOp extends Operator {

    // Performs a pivot operation - translates triples into normal rows

    Operator child;
    Map<String, String> keyMap;
    Map<String, String> foldValues;
    String attCol;
    String valCol;
    String newAlias;

    public String getAttCol() {
        return attCol;
    }

    public void setAttCol(String attCol) {
        this.attCol = attCol;
    }

    public Operator getChild() {
        return child;
    }

    public void setChild(Operator child) {
        this.child = child;
    }

    public Map<String, String> getFoldValues() {
        return foldValues;
    }

    public void setFoldValues(Map<String, String> foldValues) {
        this.foldValues = foldValues;
    }

    public Map<String, String> getKeyMap() {
        return keyMap;
    }

    public void setKeyMap(Map<String, String> keyMap) {
        this.keyMap = keyMap;
    }

    public String getNewAlias() {
        return newAlias;
    }

    public void setNewAlias(String newAlias) {
        this.newAlias = newAlias;
    }

    public String getValCol() {
        return valCol;
    }

    public void setValCol(String valCol) {
        this.valCol = valCol;
    }

    public PivotOp(Operator child, Map<String, String> keyMap, Map<String, String> foldValues,
            String attCol, String valCol, String newAlias) {
        this.child = child;
        child.parent = this;
        this.keyMap = keyMap;
        this.foldValues = foldValues;
        this.attCol = attCol;
        this.valCol = valCol;
        this.newAlias = newAlias;

        // Create output schema - make sure that the attCol and valCol columns exist
        Domain a = null;
        Domain v = null;

        this.exposedColumns = new ArrayList<String>();
        this.exposedDomains = new ArrayList<Domain>();

        for (int i = 0; i < child.exposedColumns.size(); i++) {
            if (child.exposedColumns.get(i) == attCol) {
                a = child.exposedDomains.get(i);
            } else if (child.exposedColumns.get(i) == valCol) {
                v = child.exposedDomains.get(i);
            } else {
                this.exposedColumns.add(child.exposedColumns.get(i));
                this.exposedDomains.add(child.exposedDomains.get(i));
            }
        }

        // If a/v is still null, then we didn't find correct columns, and there is an error
        try {
            if (a == null)
                throw new Exception("Did not find attribute column " + attCol + " to pivot.");
            if (v == null)
                throw new Exception("Did not find value column " + valCol + " to pivot.");
            Enumerated e = new Enumerated((List<String>) foldValues.keySet());

            // Add the pivoted columns
            for (String s : this.foldValues.keySet()) {
                this.exposedColumns.add(foldValues.get(s));
                this.exposedDomains.add(v);
            }
        } catch (Exception e) {
            System.err.println("ERROR: " + e.toString());
        }
    }

    public String getPivotValueList() {
        List<String> ks = new ArrayList<String>(this.foldValues.keySet());
        String build = "([" + ks.get(0) + "]";
        for (int i = 1; i < ks.size(); i++) {
            build = build + ", [" + ks.get(i) + "]";
        }
        build = build + ")";
        return build;
    }

    @Override
    public SqlText visit(Provider qv) {
        return qv.transform(this);
    }

    @Override
    public void visit(Channel c, String table) {
        c.mapAliases(this, table);
    }

    @Override
    public void visit(Transform t, Command c) {
        t.expand(this, c);
    }

    @Override
    public void notifyChange(Operator old, Operator newOp) {
        if (child == old) {
            child = newOp;
            newOp.parent = this;
        }
    }

    @Override
    public Operator clone() {
        return new PivotOp(child.clone(), keyMap, foldValues, attCol, valCol, newAlias);
    }

}
